#include "pollServer.hpp"
#include <unistd.h>

// PollServer构造函数
PollServer::PollServer(uint16_t port, const std::string& ip)
    : _listenSock(-1), _port(port), _ip(ip)
{
    _listenSock = Sock::Socket();         // 获取listen文件描述符
    Sock::Bind(_listenSock, _ip, _port);  // 绑定端口号
    Sock::Listen(_listenSock);            // 设置监听状态

    // 为_fd_array申请FD_CAPACITY大小的空间
    _fd_array = (struct pollfd *)malloc(FD_CAPACITY * sizeof(struct pollfd));
    if(_fd_array == nullptr)
    {
        logMessage(FATAL, "malloc _fd_array fail, %d:%s\n", errno, strerror(errno));
        exit(7);
    }

    // 为关注的文件描述符设置初始状态
    for(int i = 0; i < FD_CAPACITY; ++i)
    {
        _fd_array[i].fd = g_none_fd;
        _fd_array[i].events = _fd_array[i].revents = 0;
    }

    // 将_fd_array[0]设置为_listenSock
    _fd_array[0].fd = _listenSock;
    _fd_array[0].events = POLLIN;
}


// PollServer开始运行函数
void PollServer::start()
{
    while(true)
    {
        CheckFdArray();
        // 设置poll方法，等待方式为阻塞式等待
        int n = poll(_fd_array, FD_CAPACITY, -1);

        if(n > 0)
        {
            // 有就绪的文件描述符
            logMessage(NORMAL, "PollServer get at last one parpared fd!\n");
            PollServerHandler();   // 处理就绪的文件描述符
        }
        else if(n == 0)
        {
            // 等待超时
            logMessage(NORMAL, "wait out time!\n");
        }
        else
        {
            logMessage(ERROR, "Poll error, errno:%d, errMsg:%s\n", errno, strerror(errno));
        }
    }
}


// 处理就绪文件描述符函数
void PollServer::PollServerHandler()
{
    for(int i = 0; i < FD_CAPACITY; ++i)
    {
        // 逐个检查文件描述符的就绪情况
        if(_fd_array[i].fd != g_none_fd && _fd_array[i].revents == POLLIN)
        {
            // 判断是listen文件描述符还是普通文件描述符
            if(_fd_array[i].fd == _listenSock) Accepter(_fd_array[i].fd);
            else Reciever(i);
        }
    }
}


// 获取新链接函数定义
void PollServer::Accepter(int listenfd)
{
    std::string cli_ip;
    uint16_t cli_port;
    
    int fd = Sock::Accept(listenfd, cli_ip, cli_port);
    if(fd < 0) return;

    // 将fd添加到fd_array中去
    int index = 0;
    for(index = 0; index < FD_CAPACITY; ++index)
    {
        if(_fd_array[index].fd == g_none_fd)
        {
            _fd_array[index].fd = fd;
            _fd_array[index].events = POLLIN;
            _fd_array[index].revents = 0;
            break;
        }
    }

    if(index == FD_CAPACITY)
    {
        logMessage(ERROR, "fd_array need enlarge!\n");
    }
    else
    {
        logMessage(NORMAL, "Get a new link, fd:%d\n", fd);
    }
}


// 从客户端读取数据函数
void PollServer::Reciever(int pos)
{
    char buffer[SIZE] = { 0 };
    ssize_t n = read(_fd_array[pos].fd, buffer, SIZE - 1);

    if(n > 0)
    {
        // 读取数据成功
        buffer[n] = '\0';
        logMessage(NORMAL, "Get message from client[%d] success!\n", _fd_array[pos].fd);
        printf("Client[%d]:%s\n", _fd_array[pos].fd, buffer);
    }
    else if(n == 0)   // 对端关闭
    {
        logMessage(DEBUG, "Client[%d] close, erase Fd:%d\n", _fd_array[pos].fd, _fd_array[pos].fd);
        close(_fd_array[pos].fd);
        _fd_array[pos].fd = -1;
        _fd_array[pos].events = _fd_array[pos].revents = 0;
    }
    else  // 数据读取失败
    {
        logMessage(DEBUG, "read fail, errno:%d, errMsg:%s\n", errno, strerror(errno));
    }
}


// 打印检查fd_array函数
void PollServer::CheckFdArray()
{
    std::cout << "_fd_array[] " << std::flush;
    for(int i = 0; i < FD_CAPACITY; ++i)
    {
        if(_fd_array[i].fd == g_none_fd) continue;
        std::cout << _fd_array[i].fd << " ";
    }
    std::cout << std::endl;
}